文章目录
  1. 1. ActivityManagerService
  2. 2. ActivityManagerNative, ActivityManagerProxy与ActivityManager

Android操作系统中, 有许多个默默维护Android系统稳定正常流畅运行的幕后工作者, 对于上层App开发者来说这些工作者的名字可能是不太熟悉甚至完全陌生的, 就像电影散场时的演职人员表, 人人都知道没有他们电影完不成, 也都知道他们各有分工, 各有名谓, 但少有人清楚他们具体做了什么. 其中为人所熟知的几大系统服务之一就是ActivityManagerService, 今天我们来访谈一下这位幕后工作者.

采访者: hjhjw1991
被采访者: ActivityManagerService家族
地点: Android 4.0源码目录
时间: 2017-03-01

ActivityManagerService

  • 你好, 请简要介绍一下你自己.
    hjhjw1991你好, 大家好, 我是ActivityManagerService, 位于frameworks/base/services/java/com/android/server/am/ActivityManagerService.java. 我的父亲是ActivityManagerNative, 我的祖父是Binder. 我左手这个接口是Watchdog.Monitor, 右手的接口是BatteryStatsImpl.BatteryCallback, 我们家的关系就像下面这幅图所示:
    ActivityManagerService类关系图
    感谢我家的健康咨询师邓凡平老师为我绘制的族谱, 他将族谱放在了这里, 有兴趣的同学欢迎买他的书以表支持.

  • 好的, 我就叫你AMS可以吗?
    没问题, 大家都这么叫我.

  • AMS, 你现在的职业是什么呢?
    我现在在家族企业Android Framework上班, 日常工作也就是管理管理企业四大金刚Activity Service ContentProvider BroadcastReceiver.

  • 听起来位置很重要呢, 平时主要忙些什么呢?
    确实非常重要, 我常常忙不过来呢. 我主要负责调度和管理刚刚提到的四大金刚, 他们是我们企业的业务骨干, 几乎所有业务都交给他们去做的, 所以为了他们能安心做好分内工作, 我作为中间协调人就需要负责在业务到来的时候找到合适的执行人并通知他们去执行. 不过说是这么说, 我其实也不是直接通知他们, 像Activity, 我就是在接到相关业务的时候, 选择合适的时机让我父亲ActivityManagerNative判断一下是什么业务, 然后告诉我应该做什么, 我就根据这个具体业务, 找到具体能做这个业务的对象. 我们有一个专门的对外接口人, 他叫ActivityManagerProxy, 负责跑业务.
    比如接口人接到一个startActivity的任务, 他就拿着资料先给我父亲看一下(ActivityManagerProxy.transact->ActivityManagerNative.onTransact), 他没有权限见我父亲, 好在他手上有支可以直接接通我父亲的专属电话mRemote, 平时什么业务都是通过这支电话传递的. 据说这支电话是我祖父Binder和他的兄弟们发明的, 他们可以监听电话里所有的通信内容, 我祖父真厉害.
    我父亲一看, 原来是START_ACTIVITY_TRANSACTION这种事务, 他帮我整理整理事务资料(因为据说事务资料都是包装在一种叫做Parcel的密封材料中的, 需要特别的解封技巧, 我不太会), 然后把整理好的资料交给我. START_ACTIVITY_TRANSACTION是我父亲和接口人Proxy约定好的暗语, 我们有一整套暗语, 写在IActivityManager这个文件里面, 这文件藏在frameworks/base/core/java/android/app/IActivityManager.java, 我也有一份拷贝, 是我父亲给我的, 但我基本上没看过, 都让我父亲看(ActivityManagerService.onTransact里面就是super.onTransact), 没办法我太忙了. 据说这套暗语也是祖父发明的, 我祖父真厉害.
    父亲将资料交给我的时候也会告诉我, 要用startActivity这个方法去完成这个事务. 这个方法我知道, 我给你手写一下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
      public final int startActivity(IApplicationThread caller,
    Intent intent, String resolvedType, Uri[] grantedUriPermissions,
    int grantedMode, IBinder resultTo,
    String resultWho, int requestCode, boolean onlyIfNeeded, boolean debug,
    String profileFile, ParcelFileDescriptor profileFd, boolean autoStopProfiler) { // 方法签名
    return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
    grantedUriPermissions, grantedMode, resultTo, resultWho,
    requestCode, onlyIfNeeded, debug, profileFile, profileFd, autoStopProfiler,
    null, null); // 执行者
    }
    ```

    你看, 很简单吧, 我其实只是把资料全都交给对的家伙去处理罢了. 说得我都有点不好意思了, 我平时真的很忙的, 真的. 这个`mMainStack`是我一个得力秘书, 他专精`Activity`相关管理事务, 据说他们家族是`ActivityStack`. 我看他能力不错, 就在`main`的时候把他招进来了.
    我做的工作差不多都是这种模式, 像`startService`这种事务我可能做的事要多些, `startService -> startServiceLocked -> bringUpServiceLocked -> realStartServiceLocked -> app.thread.scheduleCreateService`, 基本上就是检查权限, 检查是不是已经在做了, 检查做的人还在不在, 如果做的人在但是还没开始做并且做的人能做, 我就交给他去做. 这个做事的人, 就是`app.thread`. `app`是`ProcessRecord`家的, 他小弟`thread`是`IApplicationThread`家的. 我虽然是`ServerThread`一手提拔起来让我做到现在位置的, 但是我们的运营完全独立于他, 行话说就是我们在**独立线程**上.

    - 你刚刚提到了`main`, 你所说的`main`是个什么过程呢?
    `main`是我的上司`SystemServer::ServerThread`(位于`frameworks/base/services/java/com/android/server/SystemServer.java`)交给我的任务. 他一旦告诉我要做`main`了, 我就要开始工作了. 具体来说, 我做的工作是这样的:

    ```
    public static final Context main(int factoryTest) {
    AThread thr = new AThread(); // #1 创建一个AThread线程对象
    thr.start();

    synchronized (thr) {
    ... // #2 等待线程的thr.mService创建完成
    }

    ActivityManagerService m = thr.mService;
    mSelf = m;
    ActivityThread at = ActivityThread.systemMain(); // #3 调用ActivityThread.systemMain函数
    mSystemThread = at;
    Context context = at.getSystemContext(); // #4 获得SystemContext
    context.setTheme(android.R.style.Theme_Holo);
    m.mContext = context;
    m.mFactoryTest = factoryTest;
    m.mMainStack = new ActivityStack(m, context, true); // #5 使用m和context新建ActivityStack对象

    m.mBatteryStatsService.publish(context); // 调用BSS和USS的publish方法
    m.mUsageStatsService.publish(context);

    synchronized (thr) {
    thr.mReady = true; // #6 设置thr为已准备, 并通知thr可以开始他的表演
    thr.notifyAll();
    }

    m.startRunning(null, null, null, null); // 全null参数调用startRunning, 主要作用是设置`mStartRunning`标志, 因为此时`mSystemReady`还是默认值`false`, 走不到后面的`systemReady`逻辑

    return context;
    }

    static class AThread extends Thread {
    ActivityManagerService mService;
    boolean mReady = false;

    public AThread() {
    super("ActivityManager"); // 设置线程名字
    }

    public void run() {
    Looper.prepare(); // 准备Looper, 估计是要用消息队列来处理消息

    android.os.Process.setThreadPriority(
    android.os.Process.THREAD_PRIORITY_FOREGROUND); // 设置线程优先级
    android.os.Process.setCanSelfBackground(false);

    ActivityManagerService m = new ActivityManagerService(); // 创建AMS对象

    synchronized (this) {
    mService = m; // AMS对象赋值给成员mService
    notifyAll(); // #7 通知其他以本线程为锁的线程, 可以获取本线程来做锁了
    }

    synchronized (this) {
    ...// #8 等待mReady被外部(也就是main所在线程)设置为true
    }
    ...

    Looper.loop(); // 开始消息循环
    }
    }
    ```
    老大让我开始`main`之后, 我就分配一个小弟`AThread thr`, 等他向我汇报(#2), 小弟汇报完(#7)就等我把老大这边交代的工作做完(#3~#6), 然后他再继续剩下的工作(#8), 并处于待命状态, 随时准备处理后面的消息.

    - 好像越来越复杂了, 又是`ActivityThread`又是`SystemServer`的, 看来我又多了几个采访对象. 想问一下`AMS`, 我注意到刚刚在你`AThread`中有一步是`new ActivityManagerService()`, 这里面做了什么能让我看一下吗?
    不能╭(╯^╰)╮. `Java`类的构造函数就像女孩子的闺房, 允许你看才能看. 我可以大概跟你说里面做了什么. 大概就是下面这样:

    ```
    private ActivityManagerService() {
    Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass()); // 日志

    File dataDir = Environment.getDataDirectory(); // /data/目录
    File systemDir = new File(dataDir, "system"); // /data/system
    systemDir.mkdirs();
    // 创建BatteryStatsService, BSS
    mBatteryStatsService = new BatteryStatsService(new File(
    systemDir, "batterystats.bin").toString());
    mBatteryStatsService.getActiveStatistics().readLocked();
    mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
    mOnBattery = DEBUG_POWER ? true
    : mBatteryStatsService.getActiveStatistics().getIsOnBattery();
    mBatteryStatsService.getActiveStatistics().setCallback(this);

    // 创建UsageStatsService, USS
    mUsageStatsService = new UsageStatsService(new File(
    systemDir, "usagestats").toString());

    GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
    ConfigurationInfo.GL_ES_VERSION_UNDEFINED); // OpenGL_ES版本

    mConfiguration.setToDefaults();
    mConfiguration.locale = Locale.getDefault();
    mProcessStats.init(); // ProcessStats, 用于统计CPU/内存信息, 解析/proc/stat文件的内容

    // 解析/data/system/packages-compat.xml文件, 获得APK的屏幕尺寸要求.
    mCompatModePackages = new CompatModePackages(this, systemDir);

    // Add ourself to the Watchdog monitors.
    Watchdog.getInstance().addMonitor(this);

    // 新线程用于定时更新系统信息
    mProcessStatsThread = new Thread("ProcessStats") {
    public void run() {
    while (true) {
    try {
    try {
    synchronized(this) {
    final long now = SystemClock.uptimeMillis();
    long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
    long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
    //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
    // + ", write delay=" + nextWriteDelay);
    if (nextWriteDelay < nextCpuDelay) {
    nextCpuDelay = nextWriteDelay;
    }
    if (nextCpuDelay > 0) {
    mProcessStatsMutexFree.set(true);
    this.wait(nextCpuDelay);
    }
    }
    } catch (InterruptedException e) {
    }
    updateCpuStatsNow();
    } catch (Exception e) {
    Slog.e(TAG, "Unexpected exception collecting process stats", e);
    }
    }
    }
    };
    mProcessStatsThread.start();
    }
    ```

    总的来说就是创建了`/data/system`目录, 实例化了BSS和USS两个服务, 创建了`ProcessStats`的实例及其运行线程, 这些都是用来监控系统状况的. 另外初始化了`mCompatModePackages`和`mConfiguration`.

    - 那`ActivityThread.systemMain()`和`ActivityManagerService.startRunning()`又做了什么呢?
    `ActivityThread.systemMain()`先禁用硬件渲染, 然后实例化了一个`ActivityThread`对象并调用了它的`attach(true)`方法, 然后把这个对象丢回来. `attach(true)`传入的参数表示调用者是否系统进程. 在系统进程下它做了以下工作:

    ```

    private void attach(boolean system) {
    sThreadLocal.set(this);
    mSystemThread = system;
    if (!system) {// 非系统进程时的处理
    } else {
    // Don't set application object here -- if the system crashes,
    // we can't display an alert, we just want to die die die.
    // 以上是源码中的注释, 绝不是我在卖萌
    // 设置显示的进程名称为system_process
    android.ddm.DdmHandleAppName.setAppName("system_process");
    try {
    // 构造Instrumentation, Context, Application, 并调用Applicaiton.onCreate()
    mInstrumentation = new Instrumentation();
    ContextImpl context = new ContextImpl();
    // 调用init时第一个参数是getSystemContext().mPackageInfo
    context.init(getSystemContext().mPackageInfo, null, this);
    Application app = Instrumentation.newApplication(Application.class, context);
    mAllApplications.add(app);
    mInitialApplication = app;
    app.onCreate();
    } catch (Exception e) {
    ...
    }
    }

    // 添加Configuration回调
    ViewRootImpl.addConfigCallback(new ComponentCallbacks2() {
    public void onConfigurationChanged(Configuration newConfig) {
    synchronized (mPackages) {
    // We need to apply this change to the resources
    // immediately, because upon returning the view
    // hierarchy will be informed about it.
    if (applyConfigurationToResourcesLocked(newConfig, null)) {
    // This actually changed the resources! Tell
    // everyone about it.
    ...
    }
    }
    }
    public void onLowMemory() {
    }
    public void onTrimMemory(int level) {
    }
    });
    }
    ```

    可见, 在系统初始化的时候以系统的身份借助了`ActivityThread`的功能, 去获取系统资源`framework-res.apk`(应用名`android`). 从这个角度来说, `SystemServer`进程实际上也是一个特殊的应用进程, 在其上运行的应用都是仅供给系统使用的. 在`systemMain`调用结束后, 就可以通过返回的`ActivityThread`实例像操作普通应用一样操作系统应用以及和`Android`环境交互了. 相当于`SystemServer`也运行在跟应用进程相似的`Android`运行环境中.
    然后`startRunning()`做的事:

    ```
    // 以全null参数调用
    public final void startRunning(String pkg, String cls, String action,
    String data) {
    synchronized(this) {
    if (mStartRunning) {
    return;
    }
    mStartRunning = true; // 设置标记, 如果已经设置过了直接返回
    mTopComponent = pkg != null && cls != null
    ? new ComponentName(pkg, cls) : null;
    mTopAction = action != null ? action : Intent.ACTION_MAIN;
    mTopData = data; // 由于传入的参数全null, 所以这里几个成员变量也是null, action则是Intent.ACTION_MAIN
    if (!mSystemReady) { // 此时mSystemReady仍为默认值false, 直接返回
    return;
    }
    }

    systemReady(null); // 重要函数, 执行完后意味着系统已经启动完毕. 代码非常长, 而且在本次调用startRunning时并不会走到这里.
    }
    ```

    - 好的, 我大概更糊涂了. 我总结一下, AMS的`main()`总共做了三点主要的工作:
    1. 新启`AThread`线程创建`AMS`实例, 在`AMS`构造函数里面, 创建BSS/USS/mProcessStats: ProcessStats/mProcessStatsThread, 用于统计系统运行状况,
    还创建了`/data/system`目录,
    并为mCompatModePackages: CompatModePackages 和 mConfiguration: Configuration 等成员变量赋值;
    2. 通过`ActivityThread.systemMain()`函数得到了一个`ActivityThread`实例, 代表了`framework-res.apk`应用所在的应用进程,
    为`SystemServer`创建了与Android环境交互的条件. 普通的应用则是应用的主线程调用`ActivityThread.main()`来获得`ActivityThread`实例;
    3. 调用`startRunning()`, 并返回第2步创建好的`Context`实例, 完成`AMS.main()`的最后一步.

    到这里为止都是`Activity`和`Application`啥的, 你前面说过跟四大金刚打交道, 那么其他几位你又是怎么跟他们打交道的呢?

    嗯, 下次有空再说吧.

    - 好的, 距离上次(2017-03-05)已经过去了一个月, 咱们继续采访吧.

    上次说到, `SystemServer::ServerThread`调用了`AMS.main()`从而为`SystemServer`创建了`Android`环境, 为`AMS`的工作做了准备.
    然而上次在`startRunning()`时留了一个悬念, 即`SystemReady()`这个函数并没有在此时被调用. `main()`执行完之后返回了`Context`实例. 那么后面发生了什么呢?
    其实, 在`SystemServer::ServerThread::run()`中可以看到, 在`main()`方法调用之后, 经过了其他一些必要的初始化(例如调用`PackageManagerService.main()`),
    然后该线程调用了`ActivityManagerService.setSystemProcess()`, 该函数定义如下:

    public static void setSystemProcess() {

    try {
        ActivityManagerService m = mSelf;
        // 向ServiceManager注册服务
        ServiceManager.addService("activity", m);// 注册本服务, 服务名activity
        ServiceManager.addService("meminfo", new MemBinder(m));// 监控内存信息
        ServiceManager.addService("gfxinfo", new GraphicsBinder(m));// 监控硬件加速信息, 可通过adb shell dumpsys gfxinfo查看,
        4.0新增
        if (MONITOR_CPU_USAGE) {
            ServiceManager.addService("cpuinfo", new CpuBinder(m));// 监控CPU使用, MONITOR_CPU_USAGE默认为true
        }
        ServiceManager.addService("permission", new PermissionController(m));// 权限管理服务
    
        //#1 通过AMS的Context获取到PackageManagerService, 查询名为"android"的ApplicationInfo
        ApplicationInfo info =
            mSelf.mContext.getPackageManager().getApplicationInfo(
                    "android", STOCK_PM_FLAGS);
        //#2 调用ActivityThread.installSystemApplicationInfo()函数
        mSystemThread.installSystemApplicationInfo(info);
    
        synchronized (mSelf) {
            //#3 使用info新建并保存ProcessRecord对象
            ProcessRecord app = mSelf.newProcessRecordLocked(
                    mSystemThread.getApplicationThread(), info,
                    info.processName);// info.processName == "system"
            app.persistent = true;
            app.pid = MY_PID;
            app.maxAdj = ProcessList.SYSTEM_ADJ;
            mSelf.mProcessNames.put(app.processName, app.info.uid, app);
            synchronized (mSelf.mPidsSelfLocked) {
                mSelf.mPidsSelfLocked.put(app.pid, app);
            }
            //#4 更新LruProcess中存储的进程的顺序
            mSelf.updateLruProcessLocked(app, true, true);
        }
    } catch (PackageManager.NameNotFoundException e) {
        throw new RuntimeException(
                "Unable to find android system package", e);
    }
    

    }

    1
    2
    3
    4
    5

    从以上代码可以看到, AMS通过PMS(PackageManagerService)查询名为"android"的ApplicationInfo, 尽管他们实质上都是在`ServerThread`同一个进程上运行,
    完全可以以本地调用的方式互相调用, 但统一通过Context来进行交互的话, 保持了与其他服务相同的交互接口, 未来对交互方式的扩展也可以直接作用到这里, 使得代码更加灵活.
    现在来看看#2. 该函数以`ApplicationInfo`为参数, 根据前面的内容, 我们知道"android"这个名字对应的package就是"framework-res.apk",
    猜测`ApplicationInfo`是其代码模型. 我们来看看这个方法的代码:

    // frameworks/core/java/android/app/ActivityThread.java
    public void installSystemApplicationInfo(ApplicationInfo info) {

    synchronized (this) {
        // 返回的ContextImpl对象就是前面在AMS的main中创建的对象
        ContextImpl context = getSystemContext();
        //#1 oops!又一次调用了init, 是不是重复了?
        context.init(new LoadedApk(this, "android", context, info,
                CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO), null, this);
    
        // give ourselves a default profiler
        // 用于性能统计
        mProfiler = new Profiler();
    }
    

    }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    看#1再次调用了`ContextImpl.init`, 似乎跟`AMS.main`中`ActivityThread.getSystemContext()`时调用的`ContextImpl.init`重复了? 仔细看看,
    原来后者虽然给`LoadedApk`的名字也是"android", 但是传入的第四个参数是`null`, 而前者#1中传入的第四个参数是指向"framework-res.apk"的`ApplicationInfo`实例.
    这就相当于`LoadedApk`指向了实际的apk包. 那么, 为什么要这样做呢? 实际上, 前面创建`ContextImpl`的时候, 并不需要用到"framework-res.apk"的东西,
    而只是希望创建一个android运行环境, 所以不需要绑定实际的包, 而此时往后需要用到"framework-res.apk"的东西了, 它的正确运行需要一个正确初始化的android运行环境,
    所以需要将代表它的`ApplicationInfo`绑定到`ContextImpl`上, 这也就是这个方法名字的含义. 由此看来接下来要做的事情就比较清晰了: 为"framework-res.apk"的运行创建或分配一个进程,
    并管理这个进程. 这些工作也是AMS完成的.
    于是我们可以看到 #3 #4 这两步就是在做进程管理. `ProcessRecord`是用于进程管理的数据结构. 通过`AMS.newProcessRecordLocked()`来创建`ProcessRecord`实例.
    到这里我们可以思考一个问题: 进程创建之后, AMS怎么跟进程进行交互? 我们想一下, AMS自己有一个进程, 这里又新建了一个进程, 那么AMS要跟新建的进程交互, 就需要进行跨进程交互. 这是不是意味着要借助Binder?
    原因可以看我以前写的Binder解析. 事实是确实如此, AMS通过Binder对其他进程进行管理, 充当桥梁的是`ActivityThread.ApplicationThread`这个类及其相关类和接口,
    这些都是Binder的标准套路, 其中`IApplicationThread`提供了操作接口, 用于启动/暂停/停止Activity.
    `ApplicationThread`的服务端实现就位于AMS要控制的那个进程的`ActivityThread`中, 具体来说就是客户端调用接口后,
    服务端`ActivityThread`会对应往自己线程的handler中发送一个消息, 而服务端`ActivityThread`自身运行在主线程中, 所以最终就是将消息发送到了服务端的主线程中处理.
    思考完这个问题, 我们来看`newProcessRecordLocked()`的代码:

    final ProcessRecord newProcessRecordLocked(IApplicationThread thread,

        ApplicationInfo info, String customProcess) {
    String proc = customProcess != null ? customProcess : info.processName;
    BatteryStatsImpl.Uid.Proc ps = null;
    BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
    synchronized (stats) {
        ps = stats.getProcessStatsLocked(info.uid, proc);// 为本进程创建一个耗电量统计项
    }
    // 创建一个ProcessRecord对象, 第二个参数就是用来和其他进程进行通信的thread
    return new ProcessRecord(ps, thread, info, proc);
    

    }

    1
    2
    3
    4
    5
    看到没有, 第一个参数就是`IApplicationThread`. 除此之外, AMS还需要更多的进程信息来管理进程, 这些信息就放在`ProcessRecord`这个数据结构中. 我们有空可以看一看这个类的实现, 它位于`frameworks/base/services/java/com/android/server/am/ProcessRecord.java`, 有一丢丢大. 我们这里只要知道,
    在构造函数中不经保存了和应用进程进行通信的`IApplicationThread`对象, 还保存了进程名, 不同状态对应的OOM_Adj值, 以及一个`ApplicationInfo`.
    一个进程虽然可以运行多个Application, 但`ProcessRecord`一般只保存该进程中最先运行的那个`Application`的`ApplicationInfo`.
    到此为止, 已经创建了一个`ProcessRecord`对象. 创建应用进程时的过程也与此类似. 和其他应用进程不同的是, 现在创建的这个对象所对应的进程是`SystemServer`. 它既然这么特殊,
    自然有一些与众不同的地方, 从上面的代码也可以看到, AMS为这个特殊的进程记录的一部分成员变量设定了特殊的值:

    // 前一步已以ApplicationInfo.processName初始化ProcessRecord, 该值为”system”
    app.persistent = true; // 该值为true表示本进程常驻内存, 即使被杀掉也会被系统重启
    app.pid = MY_PID; // 设置pid为SystemServer的pid
    app.maxAdj = ProcessList.SYSTEM_ADJ; // 设置最大OOM_Adj为系统进程默认值, -16

    1
    2
    3
    4
    5
    6
    7
    8
    9
        至此, 一个`SystemServer`对应的`ProcessRecord`就创建完毕, 紧接着AMS将它纳入自己的管理之中. AMS通过以下几个数据结构来管理包括这个进程记录在内的进程记录:
    ![process_names](/images/blogs/process_names.png)

    总结一下, `setSystemProcess()`这个方法正如其名, 它主要完成了代表`SystemServer`进程的`ProcessRecord`对象的创建, 从此将系统进程也纳入AMS管理范围. 除此之外,
    它还将AMS/meminfo/gfxinfo等服务注册到了`ServiceManager`中.

    - 好的, 你高兴就好, 你请继续.

    好, 我们再回到`SystemServer::ServerThread::run`看接下来的内容.

    try {
    // 其他内容都省略

    Slog.i(TAG, "Entropy Service");
    Slog.i(TAG, "Power Manager");
    Slog.i(TAG, "Activity Manager");
    Slog.i(TAG, "Telephony Registry");
    Slog.i(TAG, "Package Manager");
    
    ActivityManagerService.setSystemProcess();
    
    // The AccountManager must come before the ContentService
    try {
        Slog.i(TAG, "Account Manager");
    } catch (Throwable e) {
        Slog.e(TAG, "Failure starting Account Manager", e);
    }
    Slog.i(TAG, "Content Manager");
    
    Slog.i(TAG, "System Content Providers");
    ActivityManagerService.installSystemProviders();// #1
    
    Slog.i(TAG, "Vibrator Service");
    Slog.i(TAG, "Alarm Manager");
    Slog.i(TAG, "Init Watchdog");
    Slog.i(TAG, "Window Manager");
    
    ActivityManagerService.self().setWindowManager(wm);// #2
    
    // Skip Bluetooth if we have an emulator kernel
    if (SystemProperties.get("ro.kernel.qemu").equals("1")) {
        Slog.i(TAG, "No Bluetooh Service (emulator)");
    } else if (factoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
        Slog.i(TAG, "No Bluetooth Service (factory test)");
    } else {
        Slog.i(TAG, "Bluetooth Service");
    }
    

    } catch (RuntimeException e) {
    }

    1
    接下来跟AMS有关的就#1 #2两步了. #2比较好理解, 我们重点来看#1, 即`AMS.installSystemProviders()`. 代码如下:

    public static final void installSystemProviders() {

    List<ProviderInfo> providers;
    synchronized (mSelf) {
        ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID); // 通过名字和PID获取system对应的进程记录
        providers = mSelf.generateApplicationProvidersLocked(app); // #1
        if (providers != null) {
            for (int i=providers.size()-1; i>=0; i--) {
                ProviderInfo pi = (ProviderInfo)providers.get(i);
                if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) { // 移除非系统Provider
                    Slog.w(TAG, "Not installing system proc provider " + pi.name
                            + ": not system .apk");
                    providers.remove(i);
                }
            }
        }
    }
    if (providers != null) {
        mSystemThread.installSystemProviders(providers); // #2
    }
    
    mSelf.mCoreSettingsObserver = new CoreSettingsObserver(mSelf); // #3
    
    mSelf.mUsageStatsService.monitorPackages(); // #4
    

    }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    在分析代码前, 我们先说明一下为什么会有这么个方法. 在Android中SystemServer上很多Service都需要通过Settings数据库查询配置信息,
    而这个Settings数据库是Android通过agiel特殊的Provider `SettingsProvider`提供给开发者的. 该Provider位于`SettingsProvider.apk`中,
    这个apk跟`framework-re.apk`类似, 也是在`SystemServer`进程上运行. 以上代码就是加载这个Provider. 加载完毕后`SystemServer`上就同时存在两个`apk`了.
    以上步骤#3和#4我们暂且不分析, 前者是监视Settings数据库的观察者, 后者是`UsageStatsService`的工作. #1可以看出是生成Provider列表的, 而#2则是调用`ActivityThread
    .installSystemProvider()`将系统Provider装载在进程上.

    #1 里面, 首先通过`AppGlobals.getPackageManager().queryContentProviders(app.processName, app.info.uid,
    STOCK_PM_FLAGS|PackageManager.GET_URI_PERMISSION_PATTERNS)`获取到满足进程名和进程id条件的`ProviderInfo`列表.
    遍历该列表并获取或构造`ContentProviderRecord`对象(这些对象都会保存在`AMS.mProvidersByClass`中, 一看这个名字我们差不多能猜到它就是代表ContentProvider的信息了),
    然后将这个对象以名字为键放到`app.pubProviders`中,并将它对应的包名放到`app.addPackage()`中, 最后看看能否对这个Provider包进行Dex优化. 别忘记这里的`app`就是上文中的`ProcessRecord`对象.
    至此, 查询到的Provider就纳入了当前进程`SystemServer`中了. 至于怎么通过进程名和pid查找的Provider, 这里我们就暂且不说了, 会放在`PackageManager`文章中来说.
    思考题: 为什么AMS和ProcessRecord都需要保存ContentProviderRecord?

    #2 里面做剩下的工作. #1之后实际上只是保存了`ContentProvider`的信息, 并没有产生`ContentProvider`对象, #2就能产生`ContentProvider`对象.
    实际上跟标准的`ContentProvider`产生过程并无两样. 代码如下:

    public final void installSystemProviders(List providers) {

    if (providers != null) {
        installContentProviders(mInitialApplication, providers);// 第一个参数实际类型是Application
    }
    

    }

    private void installContentProviders( // 产生ContentProvider的必经之路, 标准的产生ContentProvider的方法

        Context context, List<ProviderInfo> providers) {
    final ArrayList<IActivityManager.ContentProviderHolder> results =
        new ArrayList<IActivityManager.ContentProviderHolder>();
    
    Iterator<ProviderInfo> i = providers.iterator();
    while (i.hasNext()) {
        ProviderInfo cpi = i.next();
        ...
        // 调用installProvider获得一个IContentProvider对象
        IContentProvider cp = installProvider(context, null, cpi, false);
        if (cp != null) {
            IActivityManager.ContentProviderHolder cph =
                new IActivityManager.ContentProviderHolder(cpi);
            cph.provider = cp;// IContentProvider对象与ProviderInfo对象绑定
            results.add(cph);
            // Don't ever unload this provider from the process.
            synchronized(mProviderMap) {
                mProviderRefCountMap.put(cp.asBinder(), new ProviderRefCount(10000));//引用计数
            }
        }
    }
    
    try {
    // 向AMS注册所有的ContentProvider, 第一个参数是ApplicationThread
        ActivityManagerNative.getDefault().publishContentProviders(
            getApplicationThread(), results);
    } catch (RemoteException ex) {
    }
    

    }

    1
    2
    3
    4
    5
    6
    总结一下, 以上代码做了两件事: 1. 通过`ActivityThread.installProvider`获得`ContentProvider`实例; 2. 向AMS发布所有`ContentProvider`实例.
    其实这跟`Binder Service`类似: 创建`Binder Service`实例, 向`ServiceManager`注册实例.
    `ActivityThread`和`ContentProvider`的关系如图:
    ![contentProvider](/images/blogs/activity_manager_service_content_provider.png)

    我们这里不去深入分析`ActivityThread.installProvider()`, 这个内容放到分析`ActivityThread`的时候来讲. 我们来看`AMS.publishContentProviders()`. 代码如下:

    // 此时传入的参数是caller=getApplicationThread(),即framework-res.apk所在的SystemServer进程中, 用于进程间通信的ApplicationThread客户端实例
    public final void publishContentProviders(IApplicationThread caller,

        List<ContentProviderHolder> providers) {
    if (providers == null) {
        return;
    }
    
    synchronized(this) {
        final ProcessRecord r = getRecordForAppLocked(caller);//根据调用者Binder对象找到调用者所在的进程信息
        ...
        final long origId = Binder.clearCallingIdentity();
    
        final int N = providers.size();
        for (int i=0; i<N; i++) {
            ContentProviderHolder src = providers.get(i);
            if (src == null || src.info == null || src.provider == null) {
                continue;
            }
            ContentProviderRecord dst = r.pubProviders.get(src.info.name);// 从调用者进程信息中找到对应的ContentProviderRecord
            if (dst != null) {
                ComponentName comp = new ComponentName(dst.info.packageName, dst.info.name);
                mProvidersByClass.put(comp, dst);//以ComponentName为键, 保存ContentProviderRecord. 这是寻找ContentProvider的方式之一
                String names[] = dst.info.authority.split(";");
                for (int j = 0; j < names.length; j++) {
                    mProvidersByName.put(names[j], dst);// 以authority为键, 保存ContentProviderRecord. 这是寻找ContentProvider的方式之一
                }
    
                int NL = mLaunchingProviders.size();// 处于启动状态的ContentProvider
                int j;
                for (j=0; j<NL; j++) {
                    if (mLaunchingProviders.get(j) == dst) {
                        mLaunchingProviders.remove(j);
                        j--;
                        NL--;
                    }
                }
                synchronized (dst) {
                    dst.provider = src.provider;
                    dst.proc = r;
                    dst.notifyAll();//通知所有等待中的进程, 本ContentProvider已经发布, 可供使用
                }
                updateOomAdjLocked(r);// 每发布一个ContentProvider, 调整一次调用者进程的oom_adj
            }
        }
    
        Binder.restoreCallingIdentity(origId);
    }
    

    }

    1
    2
    3
    总结一下, `SettingsProvider.apk`作为一个系统级的`ContentProvider`,
    通过`installSystemProvider`由`SystemServer`进程走普通的`ContentProvider`创建和发布流程完成发布.
    接着我们再回到`SystemServer::ServerThread::run`, 走余下的流程:

    // in file SystemServer.java

    // We now tell the activity manager it is okay to run third party
    // code. It will call back into us once it has gotten to the state
    // where third party code can really run (but before it has actually
    // started launching the initial applications), for us to complete our
    // initialization.
    ActivityManagerService.self().systemReady(new Runnable() {

    public void run() {
        Slog.i(TAG, "Making services ready");
    
        startSystemUi(contextF);
        try {
            if (batteryF != null) batteryF.systemReady();
        } catch (Throwable e) {
            reportWtf("making Battery Service ready", e);
        }
        try {
            if (networkManagementF != null) networkManagementF.systemReady();
        } catch (Throwable e) {
            reportWtf("making Network Managment Service ready", e);
        }
        try {
            if (networkStatsF != null) networkStatsF.systemReady();
        } catch (Throwable e) {
            reportWtf("making Network Stats Service ready", e);
        }
        try {
            if (networkPolicyF != null) networkPolicyF.systemReady();
        } catch (Throwable e) {
            reportWtf("making Network Policy Service ready", e);
        }
        try {
            if (connectivityF != null) connectivityF.systemReady();
        } catch (Throwable e) {
            reportWtf("making Connectivity Service ready", e);
        }
        try {
            if (dockF != null) dockF.systemReady();
        } catch (Throwable e) {
            reportWtf("making Dock Service ready", e);
        }
        try {
            if (usbF != null) usbF.systemReady();
        } catch (Throwable e) {
            reportWtf("making USB Service ready", e);
        }
        try {
            if (uiModeF != null) uiModeF.systemReady();
        } catch (Throwable e) {
            reportWtf("making UI Mode Service ready", e);
        }
        try {
            if (recognitionF != null) recognitionF.systemReady();
        } catch (Throwable e) {
            reportWtf("making Recognition Service ready", e);
        }
        Watchdog.getInstance().start();
    
        // It is now okay to let the various system services start their
        // third party code...
    
        try {
            if (appWidgetF != null) appWidgetF.systemReady(safeMode);
        } catch (Throwable e) {
            reportWtf("making App Widget Service ready", e);
        }
        try {
            if (wallpaperF != null) wallpaperF.systemReady();
        } catch (Throwable e) {
            reportWtf("making Wallpaper Service ready", e);
        }
        try {
            if (immF != null) immF.systemReady(statusBarF);
        } catch (Throwable e) {
            reportWtf("making Input Method Service ready", e);
        }
        try {
            if (locationF != null) locationF.systemReady();
        } catch (Throwable e) {
            reportWtf("making Location Service ready", e);
        }
        try {
            if (countryDetectorF != null) countryDetectorF.systemReady();
        } catch (Throwable e) {
            reportWtf("making Country Detector Service ready", e);
        }
        try {
            if (throttleF != null) throttleF.systemReady();
        } catch (Throwable e) {
            reportWtf("making Throttle Service ready", e);
        }
        try {
            if (networkTimeUpdaterF != null) networkTimeUpdaterF.systemReady();
        } catch (Throwable e) {
            reportWtf("making Network Time Service ready", e);
        }
        try {
            if (textServiceManagerServiceF != null) textServiceManagerServiceF.systemReady();
        } catch (Throwable e) {
            reportWtf("making Text Services Manager Service ready", e);
        }
    }
    

    });

    1
    可以看到传给了`AMS.systemReady()`一个`Runnable`的回调. 是时候打开`ActivityManagerService.systemReady()`看一看了. 源码如下:

    // todo 添加源码
    `

ActivityManagerNative, ActivityManagerProxy与ActivityManager

文章目录
  1. 1. ActivityManagerService
  2. 2. ActivityManagerNative, ActivityManagerProxy与ActivityManager